package api

import (
	"context"
	"fmt"
	"net/http"
	"strconv"

	"pceservice/internal/pce"
	"pceservice/internal/pce/strategy" // todo 待优化删除
	"pceservice/internal/topology"
	"pceservice/pkg/gopcep"

	"github.com/gin-gonic/gin"
)

// Config API服务器配置
type Config struct {
	Address string `yaml:"address"`
}

// Server API服务器
type Server struct {
	config      Config
	engine      *gin.Engine
	topoManager *topology.Manager
	pathEngine  *pce.Engine
	pcepClient  *gopcep.PCEPClient
}

// NewServer 创建新的API服务器
func NewServer(config Config, topoManager *topology.Manager, pathEngine *pce.Engine, pcepClient *gopcep.PCEPClient) *Server {
	engine := gin.Default()

	s := &Server{
		config:      config,
		engine:      engine,
		topoManager: topoManager,
		pathEngine:  pathEngine,
		pcepClient:  pcepClient,
	}

	// 注册路由
	s.registerRoutes()

	return s
}

// registerRoutes 注册API路由
func (s *Server) registerRoutes() {
	api := s.engine.Group("/api/pceservice/")

	{
		api.GET("/health", health)
		// 拓扑API
		api.GET("/topology/nodes", s.getNodes)
		api.GET("/topology/links", s.getLinks)

		// 路径计算API
		api.POST("/path/calculate", s.calculatePath)
		api.POST("/path/calculate-evaluate", s.calculateAndEvaluatePath)
		api.POST("/path/multiple", s.calculateMultiplePaths)
		api.POST("/path/best", s.calculateBestPath)

		// PCEP API
		api.GET("/pcep/sessions", s.getPCEPSessions)
		api.POST("/pcep/policy", s.createSRv6Policy)
	}

	// 静态文件服务（Web UI）
s.engine.StaticFS("/", http.Dir("./webui"))
}

func health(c *gin.Context) {
	Success(c, gin.H{
		"status":  "ok",
		"message": "Service is healthy",
	})
}

// Start 启动API服务器
func (s *Server) Start() error {
	return s.engine.Run(s.config.Address)
}

// Shutdown 优雅关闭API服务器
func (s *Server) Shutdown(ctx context.Context) error {
	srv := &http.Server{
		Addr:    s.config.Address,
		Handler: s.engine,
	}
	return srv.Shutdown(ctx)
}

// getNodes 获取所有节点
func (s *Server) getNodes(c *gin.Context) {
	pageStr := c.Query("page")
	sizeStr := c.Query("size")

	var page, size int64 = 1, 10 // 默认值

	if p, err := strconv.ParseInt(pageStr, 10, 64); err == nil && p > 0 {
		page = p
	}

	if s, err := strconv.ParseInt(sizeStr, 10, 64); err == nil && s > 0 {
		size = s
	}

	nodes, total, err := s.topoManager.GetNodesWithPagination(page, size)
	if err != nil {
		InternalServerError(c, err)
		return
	}

	// 分页
	Paginate(c, nodes, total)
}

// getLinks 获取所有链路
func (s *Server) getLinks(c *gin.Context) {
	pageStr := c.Query("page")
	sizeStr := c.Query("size")

	var page, size int64 = 1, 10 // 默认值

	if p, err := strconv.ParseInt(pageStr, 10, 64); err == nil && p > 0 {
		page = p
	}

	if s, err := strconv.ParseInt(sizeStr, 10, 64); err == nil && s > 0 {
		size = s
	}

	links, total, err := s.topoManager.GetLinksWithPagination(page, size)
	if err != nil {
		InternalServerError(c, err)
		return
	}

	Paginate(c, links, total)
}

// CalculatePathRequest 路径计算请求
type CalculatePathRequest struct {
	Source      string            `json:"source"`
	Destination string            `json:"destination"`
	Constraints []*PathConstraint `json:"constraints"`
}

// CalculateAndEvaluatePathRequest 计算并评估路径请求
type CalculateAndEvaluatePathRequest struct {
	Source      string            `json:"source"`
	Destination string            `json:"destination"`
	Constraints []*PathConstraint `json:"constraints"`
	DelayWeight      float64       `json:"delayWeight,omitempty"`
	HopWeight        float64       `json:"hopWeight,omitempty"`
	CostWeight       float64       `json:"costWeight,omitempty"`
	BandwidthWeight  float64       `json:"bandwidthWeight,omitempty"`
}

// CalculateBestPathRequest 计算最佳路径请求
type CalculateBestPathRequest struct {
	Source      string  `json:"source"`
	Destination string  `json:"destination"`
	DelayWeight      float64 `json:"delayWeight,omitempty"`
	HopWeight        float64 `json:"hopWeight,omitempty"`
	CostWeight       float64 `json:"costWeight,omitempty"`
	BandwidthWeight  float64 `json:"bandwidthWeight,omitempty"`
}

// PathConstraint 路径约束
type PathConstraint struct {
	Type  strategy.ConstraintType `json:"type"`
	Nodes []string                `json:"nodes,omitempty"`
}

// calculateAndEvaluatePath 计算并评估路径
func (s *Server) calculateAndEvaluatePath(c *gin.Context) {
	var req CalculateAndEvaluatePathRequest

	// 解析请求
	if err := c.ShouldBindJSON(&req); err != nil {
		BadRequest(c, err)
		return
	}

	// 检查源节点和目标节点是否为空
	if req.Source == "" || req.Destination == "" {
		BadRequest(c, fmt.Errorf("源节点和目标节点不能为空"))
		return
	}

	// 构建策略配置
	mustPassCfg := &strategy.MustPassConfig{}
	mustNotPassCfg := &strategy.MustNotPassConfig{}

	// 创建约束列表
	var constraintTypes []strategy.ConstraintType
	for _, pc := range req.Constraints {
		switch pc.Type {
		case strategy.MinHop:
			constraintTypes = append(constraintTypes, strategy.MinHop)
		case strategy.MinDelay:
			constraintTypes = append(constraintTypes, strategy.MinDelay)
		case strategy.BalancedBandwidth:
			constraintTypes = append(constraintTypes, strategy.BalancedBandwidth)
		case strategy.MinCost:
			constraintTypes = append(constraintTypes, strategy.MinCost)
		case strategy.MustPass:
			constraintTypes = append(constraintTypes, strategy.MustPass)
			mustPassCfg.Nodes = append(mustPassCfg.Nodes, pc.Nodes...)
		case strategy.MustNotPass:
			constraintTypes = append(constraintTypes, strategy.MustNotPass)
			mustNotPassCfg.Nodes = append(mustNotPassCfg.Nodes, pc.Nodes...)
		}
	}

	// 创建策略
	constraint := strategy.Constraint{
		Constraints: constraintTypes,
	}

	strategyObj := strategy.CreateStrategy(constraint, mustPassCfg, mustNotPassCfg)

	// 创建路径评估器（如果提供了权重）
	if req.DelayWeight > 0 || req.HopWeight > 0 || req.CostWeight > 0 || req.BandwidthWeight > 0 {
		// 确保权重和不为0
		totalWeight := req.DelayWeight + req.HopWeight + req.CostWeight + req.BandwidthWeight
		if totalWeight == 0 {
			BadRequest(c, fmt.Errorf("权重和不能为0"))
			return
		}
		s.pathEngine.SetPathEvaluator(pce.NewPathEvaluator(req.DelayWeight, req.HopWeight, req.CostWeight, req.BandwidthWeight))
	} else {
		// 使用默认评估器
		s.pathEngine.CreateDefaultPathEvaluator()
	}

	// 计算并评估路径
	path, result, err := s.pathEngine.CalculateAndEvaluatePath(strategyObj, req.Source, req.Destination)
	if err != nil {
		InternalServerError(c, err)
		return
	}

	Success(c, gin.H{
		"path":   path,
		"result": result,
	})
}

// calculateMultiplePaths 计算多条路径
func (s *Server) calculateMultiplePaths(c *gin.Context) {
	var req CalculatePathRequest

	// 解析请求
	if err := c.ShouldBindJSON(&req); err != nil {
		BadRequest(c, err)
		return
	}

	// 检查源节点和目标节点是否为空
	if req.Source == "" || req.Destination == "" {
		BadRequest(c, fmt.Errorf("源节点和目标节点不能为空"))
		return
	}

	// 计算多条路径
	paths, err := s.pathEngine.CalculateMultiplePaths(req.Source, req.Destination)
	if err != nil {
		InternalServerError(c, err)
		return
	}

	Success(c, paths)
}

// calculateBestPath 计算最佳路径
func (s *Server) calculateBestPath(c *gin.Context) {
	var req CalculateBestPathRequest

	// 解析请求
	if err := c.ShouldBindJSON(&req); err != nil {
		BadRequest(c, err)
		return
	}

	// 检查源节点和目标节点是否为空
	if req.Source == "" || req.Destination == "" {
		BadRequest(c, fmt.Errorf("源节点和目标节点不能为空"))
		return
	}

	// 创建路径评估器（如果提供了权重）
	if req.DelayWeight > 0 || req.HopWeight > 0 || req.CostWeight > 0 || req.BandwidthWeight > 0 {
		// 确保权重和不为0
		totalWeight := req.DelayWeight + req.HopWeight + req.CostWeight + req.BandwidthWeight
		if totalWeight == 0 {
			BadRequest(c, fmt.Errorf("权重和不能为0"))
			return
		}
		s.pathEngine.SetPathEvaluator(pce.NewPathEvaluator(req.DelayWeight, req.HopWeight, req.CostWeight, req.BandwidthWeight))
	} else {
		// 使用默认评估器
		s.pathEngine.CreateDefaultPathEvaluator()
	}

	// 计算最佳路径
	path, result, err := s.pathEngine.CalculateBestPath(req.Source, req.Destination)
	if err != nil {
		InternalServerError(c, err)
		return
	}

	Success(c, gin.H{
		"path":   path,
		"result": result,
	})
}

// calculatePath 计算路径
func (s *Server) calculatePath(c *gin.Context) {
	var req CalculatePathRequest

	// 解析请求
	if err := c.ShouldBindJSON(&req); err != nil {
		BadRequest(c, err)
		return
	}

	// 检查源节点和目标节点是否为空
	if req.Source == "" || req.Destination == "" {
		BadRequest(c, fmt.Errorf("源节点和目标节点不能为空"))
		return
	}

	// 构建策略配置
	mustPassCfg := &strategy.MustPassConfig{}
	mustNotPassCfg := &strategy.MustNotPassConfig{}

	// 创建约束列表
	var constraintTypes []strategy.ConstraintType
	for _, pc := range req.Constraints {
		switch pc.Type {
		case strategy.MinHop:
			constraintTypes = append(constraintTypes, strategy.MinHop)
		case strategy.MinDelay:
			constraintTypes = append(constraintTypes, strategy.MinDelay)
		case strategy.BalancedBandwidth:
			constraintTypes = append(constraintTypes, strategy.BalancedBandwidth)
		case strategy.MinCost:
			constraintTypes = append(constraintTypes, strategy.MinCost)
		case strategy.MustPass:
			constraintTypes = append(constraintTypes, strategy.MustPass)
			mustPassCfg.Nodes = append(mustPassCfg.Nodes, pc.Nodes...)
		case strategy.MustNotPass:
			constraintTypes = append(constraintTypes, strategy.MustNotPass)
			mustNotPassCfg.Nodes = append(mustNotPassCfg.Nodes, pc.Nodes...)
		}
	}

	// 创建策略工厂
	constraint := strategy.Constraint{
		Constraints: constraintTypes,
	}

	strategyObj := strategy.CreateStrategy(constraint, mustPassCfg, mustNotPassCfg)

	// 调用路径计算引擎
	path, err := s.pathEngine.CalculatePath(strategyObj, req.Source, req.Destination)
	if err != nil {
		InternalServerError(c, fmt.Errorf("路径计算失败: %v", err))
		return
	}

	// 返回结果
	Success(c, gin.H{
		"path": path,
	})
}

// getPCEPSessions 获取PCEP会话
func (s *Server) getPCEPSessions(c *gin.Context) {
	// todo 调用gopcep的api
	// 示例：返回空会话列表
	Success(c, gin.H{"sessions": []string{}})
}

// CreateSRv6PolicyRequest 创建SRv6策略请求
type CreateSRv6PolicyRequest struct {
	Name        string            `json:"name"`
	Source      string            `json:"source"`
	Destination string            `json:"destination"`
	Color       int               `json:"color"`
	Constraints []*PathConstraint `json:"constraints"` // 算路约束
}

// createSRv6Policy 创建SRv6策略
func (s *Server) createSRv6Policy(c *gin.Context) {
	var req CreateSRv6PolicyRequest

	// 解析请求
	if err := c.ShouldBindJSON(&req); err != nil {
		BadRequest(c, err)
		return
	}

	// 这里应该调用PCEP客户端发送SRv6策略

	// todo 待实现  api消息转换为gopcepapi.InitiatedLsp 并调用 s.pcepClient.SendMessage

	// 简化示例，返回成功

	response := gin.H{
		"status":  "success",
		"message": "SRv6策略已成功创建",
		"policy":  req,
	}

	Success(c, response)
}
